import asyncio
import datetime
import sqlite3
import sys
import time
import traceback
from io import StringIO

from bson import ObjectId
from fastapi import APIRouter, Request
from pymongo.errors import DocumentTooLarge
from re_common.baselibrary.utils.basedir import BaseDir
from re_common.baselibrary.utils.basefile import BaseFile
from re_common.baselibrary.utils.core.mdeprecated import try_except2_async
from starlette.responses import FileResponse, StreamingResponse

from apps.allsubdb.test.models import Test
from apps.core.m_route import ContextIncludedRoute
from apps.core.return_info import ReturnInfo, SUCCESS, InputInfoModel
from apps.sql_app.mmongodb import Coll

router = APIRouter(route_class=ContextIncludedRoute)  #


@router.get("/hello")
def read_root():
    return "Hello World"


@router.get("/strings")
async def down_wanfangqklist():
    """
    以a到z 请求json 获取列表
    :param proxy:
    :param rawid:
    :param page:
    :return:
    """
    return_info = ReturnInfo()
    return_info.status = SUCCESS
    return_info.msg_code = 200
    return_info.msg = "test"
    return_info.data = {"test1": "test2", "test3": "test4"}
    return return_info.todict()


@router.get("/test_event")
async def down_wanfangqklist():
    """
    以a到z 请求json 获取列表
    :param proxy:
    :param rawid:
    :param page:
    :return:
    """
    await asyncio.sleep(10)
    return_info = ReturnInfo()
    return_info.status = SUCCESS
    return_info.msg_code = 200
    return_info.msg = "test"
    return_info.data = {"test1": "test2", "test3": "test4"}
    return return_info.todict()


@router.post("/test_error")
async def down_wanfangqklist(input: InputInfoModel[Test]):
    """
    以a到z 请求json 获取列表
    :param proxy:
    :param rawid:
    :param page:
    :return:
    """

    class UnicornException(Exception):
        def __init__(self, name: str):
            self.name = name

    return_info = ReturnInfo()
    # a = 1 / 0
    raise UnicornException(name="test")
    return_info.status = SUCCESS
    return_info.msg_code = 200
    return_info.msg = "test"
    return_info.data = {"test1": "test2", "test3": "test4"}
    return return_info.todict()


async def all_client_back_callback(*args, **kwargs):
    """
        处理返回值 确定是否进行存储
    :param self:
    :return:
    """
    from app_main import request_ctx_var
    from main import app
    from apps.file_uploadfile.models import ServerErrModel
    try_his = request_ctx_var.get().state.try_his
    try_his.append(traceback.format_exc())
    request = request_ctx_var.get()
    m = ServerErrModel().dict()
    m["ip_port"] = app.state.ip + ":" + str(app.state.port)
    m["client_ip"] = str(request.client.host)
    m["write_time"] = str(datetime.datetime.now())
    m["request_url"] = str(request.url)
    # https://github.com/tiangolo/fastapi/issues/1216 作者目前还没有解决这个bug
    # m.request_body = body.decode()
    m["request_body"] = str(request.state.mbody)
    m["err_type"] = str(sys.exc_info()[0])
    m["err_msg"] = str(sys.exc_info()[1])
    m["traceback_str"] = traceback.format_exc()
    save_dicts = ServerErrModel.parse_obj(m)
    m_result = Coll.get_server_exception()
    result = await m_result.insert_one(save_dicts.dict(by_alias=True))
    exception_list = ["proxy"]
    for i in exception_list:
        if i in traceback.format_exc():
            return False, {"traceback": traceback.format_exc(), "need_save": False}
    return False, {"traceback": traceback.format_exc(), "need_save": True}


@try_except2_async(callback=all_client_back_callback, is_print=True)
async def test():
    a = 1 / 0
    return True, ""


@router.post("/test_error_get")
async def down_wanfangqklist(input: InputInfoModel[Test]):
    """
    修改测试装饰器用
    :param proxy:test
    :param rawid:
    :param page:
    :return:
    """
    return_info = ReturnInfo()
    # a = 1 / 0
    bools, err = await test()
    return_info.status = SUCCESS
    return_info.msg_code = 200
    return_info.msg = "test"
    return_info.data = {"test1": "test2", "test3": "test4"}
    return return_info.todict()


@router.get("/return_none")
async def down_wanfangqklist():
    pass


@router.get("/return_file")
async def return_file():
    # 放到当前目录下的子目录会导致任务重加载
    temp = "..\\fastapi_cjserver_temp"
    if not BaseDir.is_dir_exists(temp):
        BaseDir.create_dir(temp)
    for file in BaseDir.get_dir_all_files(temp):
        if time.time() - BaseFile.get_update_time(file) > 60 * 10:  #
            if BaseFile.is_file_exists(file):
                BaseFile.remove_file(file)
    filepath = '{}\\{}.db3'.format(temp, time.time())
    con = sqlite3.connect(":memory:")
    cur = con.cursor()
    cur.execute(
        """CREATE TABLE "quotes" ("rid" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"code" TEXT(10) NOT NULL,"high" TEXT,"open" TEXT,"low" TEXT,"close" TEXT,"amount" TEXT,"volume" TEXT);""")
    cur.execute('insert into quotes(code,high,open,low,close,amount,volume) values(?,?,?,?,?,?,?)',
                ('600036', '12.0', '11.8', '11.7', '11.9', '999999', '8999'))
    # str_buffer = StringIO()
    # for line in con.iterdump():
    #     str_buffer.write('%s\n' % line)

    # cur.execute("select * from quotes")

    # 打开文件数据库

    # con_file = sqlite3.connect(filepath)
    # cur_file = con_file.cursor()
    # # 执行内存数据库脚本
    # cur_file.executescript(str_buffer.getvalue())
    # # 关闭文件数据库
    # cur_file.close()
    # cur.close()
    # response = StreamingResponse(iter([str_buffer.getvalue()]), media_type='text/plain')
    # response.headers["Content-Disposition"] = "attachment; filename=test.db3"

    return FileResponse(filepath, filename='test.db3')
    # return response


@router.get(path='/test/{a}')
async def test(request: Request):
    res = {
        # 客户端连接的 host
        "host": request.client.host,
        # 客户端连接的端口号
        "port": request.client.port,
        # 请求方法
        "method": request.method,
        # 请求路径
        "base_url": request.base_url,
        # request headers
        "headers": request.headers,
        # request cookies
        "cookies": request.cookies,
        # 请求 url
        "url": request.url,
        # 请求组成
        "components": request.url.components,
        # 请求协议
        "scheme": request.url.scheme,
        # 请求 host
        "hostname": request.url.hostname,
        # 请求端口
        "url_port": request.url.port,
        # 请求 path
        "path": request.url.path,
        # 请求查询参数
        "query": request.url.query,
        # 获取路径参数
        "path_params": request.path_params,
        # 获取查询参数
        "query_params": request.query_params
    }
    return res


@router.get("/get_baseurl")
async def down_wanfangqklist():
    from settings import URLDISTRIBUTED
    url = await URLDISTRIBUTED.get_base_url(tag='para_url')
    print(url)
    return url
